libxc: User-space grant table device.
authorKeir Fraser <keir@xensource.com>
Sat, 31 Mar 2007 13:03:17 +0000 (14:03 +0100)
committerKeir Fraser <keir@xensource.com>
Sat, 31 Mar 2007 13:03:17 +0000 (14:03 +0100)
Changes to libxc to enable easy access to the grant table device.

Signed-off-by: Derek Murray <Derek.Murray@cl.cam.ac.uk>
tools/libxc/xc_linux.c
tools/libxc/xenctrl.h

index eac5acc79369eade562cdfe31945703b0e5b0afd..cab3c6588f2020394198a1758f37a10a20a549e8 100644 (file)
@@ -3,6 +3,9 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  *
+ * xc_gnttab functions:
+ * Copyright (c) 2007, D G Murray <Derek.Murray@cl.cam.ac.uk>
+ *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation, version 2 of the
@@ -13,6 +16,7 @@
 
 #include <xen/memory.h>
 #include <xen/sys/evtchn.h>
+#include <xen/sys/gntdev.h>
 #include <unistd.h>
 #include <fcntl.h>
 
@@ -363,6 +367,158 @@ void discard_file_cache(int fd, int flush)
     errno = saved_errno;
 }
 
+#define GNTTAB_DEV_NAME "/dev/xen/gntdev"
+
+int xc_gnttab_open(void)
+{
+    struct stat st;
+    int fd;
+    int devnum;
+    
+    devnum = xc_find_device_number("gntdev");
+    
+    /* Make sure any existing device file links to correct device. */
+    if ( (lstat(GNTTAB_DEV_NAME, &st) != 0) || !S_ISCHR(st.st_mode) ||
+         (st.st_rdev != devnum) )
+        (void)unlink(GNTTAB_DEV_NAME);
+    
+reopen:
+    if ( (fd = open(GNTTAB_DEV_NAME, O_RDWR)) == -1 )
+    {
+        if ( (errno == ENOENT) &&
+             ((mkdir("/dev/xen", 0755) == 0) || (errno == EEXIST)) &&
+             (mknod(GNTTAB_DEV_NAME, S_IFCHR|0600, devnum) == 0) )
+            goto reopen;
+        
+        PERROR("Could not open grant table interface");
+        return -1;
+    }
+    
+    return fd;
+}
+
+int xc_gnttab_close(int xcg_handle)
+{
+    return close(xcg_handle);
+}
+
+void *xc_gnttab_map_grant_ref(int xcg_handle,
+                              uint32_t domid,
+                              uint32_t ref,
+                              int prot)
+{
+    struct ioctl_gntdev_map_grant_ref map;
+    void *addr;
+    
+    map.count = 1;
+    map.refs[0].domid = domid;
+    map.refs[0].ref   = ref;
+
+    if ( ioctl(xcg_handle, IOCTL_GNTDEV_MAP_GRANT_REF, &map) )
+        return NULL;
+    
+    addr = mmap(NULL, PAGE_SIZE, prot, MAP_SHARED, xcg_handle, map.index);
+    if ( addr == MAP_FAILED )
+    {
+        int saved_errno = errno;
+        struct ioctl_gntdev_unmap_grant_ref unmap_grant;
+        /* Unmap the driver slots used to store the grant information. */
+        unmap_grant.index = map.index;
+        unmap_grant.count = 1;
+        ioctl(xcg_handle, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
+        errno = saved_errno;
+        return NULL;
+    }
+    
+    return addr;
+}
+
+void *xc_gnttab_map_grant_refs(int xcg_handle,
+                               uint32_t count,
+                               uint32_t domids[count],
+                               uint32_t refs[count],
+                               int prot)
+{
+    struct ioctl_gntdev_map_grant_ref *map;
+    void *addr = NULL;
+    int i;
+    
+    map = malloc(sizeof(*map) +
+                 (count-1) * sizeof(struct ioctl_gntdev_map_grant_ref));
+    if ( map == NULL )
+        return NULL;
+
+    for ( i = 0; i < count; i++ )
+    {
+        map->refs[i].domid = domids[i];
+        map->refs[i].ref   = refs[i];
+    }
+
+    map->count = count;
+    
+    if ( ioctl(xcg_handle, IOCTL_GNTDEV_MAP_GRANT_REF, &map) )
+        goto out;
+
+    addr = mmap(NULL, PAGE_SIZE * count, prot, MAP_SHARED, xcg_handle,
+                map->index);
+    if ( addr == MAP_FAILED )
+    {
+        int saved_errno = errno;
+        struct ioctl_gntdev_unmap_grant_ref unmap_grant;
+        /* Unmap the driver slots used to store the grant information. */
+        unmap_grant.index = map->index;
+        unmap_grant.count = count;
+        ioctl(xcg_handle, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant);
+        errno = saved_errno;
+        addr = NULL;
+    }
+
+ out:
+    free(map);
+    return addr;
+}
+
+int xc_gnttab_munmap(int xcg_handle,
+                     void *start_address,
+                     uint32_t count)
+{
+    struct ioctl_gntdev_get_offset_for_vaddr get_offset;
+    struct ioctl_gntdev_unmap_grant_ref unmap_grant;
+    int rc;
+
+    if ( start_address == NULL )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    /* First, it is necessary to get the offset which was initially used to
+     * mmap() the pages.
+     */
+    get_offset.vaddr = (unsigned long)start_address;
+    if ( (rc = ioctl(xcg_handle, IOCTL_GNTDEV_GET_OFFSET_FOR_VADDR, 
+                     &get_offset)) )
+        return rc;
+
+    if ( get_offset.count != count )
+    {
+        errno = EINVAL;
+        return -1;
+    }
+
+    /* Next, unmap the memory. */
+    if ( (rc = munmap(start_address, count * getpagesize())) )
+        return rc;
+    
+    /* Finally, unmap the driver slots used to store the grant information. */
+    unmap_grant.index = get_offset.offset;
+    unmap_grant.count = count;
+    if ( (rc = ioctl(xcg_handle, IOCTL_GNTDEV_UNMAP_GRANT_REF, &unmap_grant)) )
+        return rc;
+
+    return 0;
+}
+
 /*
  * Local variables:
  * mode: C
index 4b346a74f09e07c2052d8cb04f27958ebbbf97f8..f838b70966bf436ae7f63420584459c93746c1ff 100644 (file)
@@ -4,6 +4,9 @@
  * A library for low-level access to the Xen control interfaces.
  *
  * Copyright (c) 2003-2004, K A Fraser.
+ *
+ * xc_gnttab functions:
+ * Copyright (c) 2007, D G Murray <Derek.Murray@cl.cam.ac.uk>
  */
 
 #ifndef XENCTRL_H
@@ -740,6 +743,62 @@ evtchn_port_t xc_evtchn_pending(int xce_handle);
  */
 int xc_evtchn_unmask(int xce_handle, evtchn_port_t port);
 
+/**************************
+ * GRANT TABLE OPERATIONS *
+ **************************/
+
+/*
+ * Return a handle to the grant table driver, or -1 on failure, in which case
+ * errno will be set appropriately.
+ */
+int xc_gnttab_open(void);
+
+/*
+ * Close a handle previously allocated with xc_gnttab_open().
+ */
+int xc_gnttab_close(int xcg_handle);
+
+/*
+ * Memory maps a grant reference from one domain to a local address range.
+ * Mappings should be unmapped with xc_gnttab_munmap.  Returns NULL on failure.
+ *
+ * @parm xcg_handle a handle on an open grant table interface
+ * @parm domid the domain to map memory from
+ * @parm ref the grant reference ID to map
+ * @parm prot same flag as in mmap()
+ */
+void *xc_gnttab_map_grant_ref(int xcg_handle,
+                              uint32_t domid,
+                              uint32_t ref,
+                              int prot);
+
+/**
+ * Memory maps one or more grant references from one or more domains to a
+ * contiguous local address range. Mappings should be unmapped with
+ * xc_gnttab_munmap.  Returns NULL on failure.
+ *
+ * @parm xcg_handle a handle on an open grant table interface
+ * @parm count the number of grant references to be mapped
+ * @parm domids an array of @count domain IDs by which the corresponding @refs
+ *              were granted
+ * @parm refs an array of @count grant references to be mapped
+ * @parm prot same flag as in mmap()
+ */
+void *xc_gnttab_map_grant_refs(int xcg_handle,
+                               uint32_t count,
+                               uint32_t domids[count],
+                               uint32_t refs[count],
+                               int prot);
+
+/*
+ * Unmaps the @count pages starting at @start_address, which were mapped by a
+ * call to xc_gnttab_map_grant_ref or xc_gnttab_map_grant_refs. Returns zero
+ * on success, otherwise sets errno and returns non-zero.
+ */
+int xc_gnttab_munmap(int xcg_handle,
+                     void *start_address,
+                     uint32_t count);
+
 int xc_hvm_set_pci_intx_level(
     int xc_handle, domid_t dom,
     uint8_t domain, uint8_t bus, uint8_t device, uint8_t intx,